package cn.lwj.webService.util;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import org.xml.sax.InputSource;

public class XmlXStreamUtils {
	/**
	 * 对象转XML
	 * @param obj 需要转换的对象
	 * @param aliasMap 对象的别名集合
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static String objectToXml(Integer headerFlag,Object obj,Map<String,Class> aliasMap){
		XStream xStream=new XStream(new DomDriver());
		if(obj != null){
			if(aliasMap!=null&&aliasMap.size()>0){
				Iterator<String> it = aliasMap.keySet().iterator();
				while(it.hasNext()){
					String key = it.next();
					xStream.alias(key, aliasMap.get(key));
				}
			}

			xStream.setMode(XStream.NO_REFERENCES);
			try {
				for (Field f:obj.getClass().getDeclaredFields()) {
					if(f.getName().equals("xmlnsXsi"))
						xStream.useAttributeFor(obj.getClass(), "xmlnsXsi");
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			xStream.aliasField("xmlns:xsi", obj.getClass(), "xmlnsXsi");

			xStream.aliasSystemAttribute(null, "class");

			xStream.registerConverter(new BlobConverter());
			xStream.registerConverter(new NullToXmlConverter());
			xStream.registerConverter(new IntegerConverter());
			xStream.registerConverter(new DateConverter());
		}

		//xStream.registerConverter(new DoubleConverter());
//		System.out.println(obj==null?null:"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"+xStream.toXML(obj));
		if(headerFlag==1){
			return  obj==null?null:"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"+xStream.toXML(obj);
		}else{
			return  obj==null?null:xStream.toXML(obj);
		}
		
	}
	
	/**
	 * XML转JAVA对象
	 * @param xml XML格式的字符串
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static Object xmlToObject(String xml,Map<String,Class> aliasMap){
		XStream xStream=new XStream(new DomDriver());
		if (aliasMap != null && aliasMap.size() > 0) {
			Iterator<String> it = aliasMap.keySet().iterator();
			while (it.hasNext()) {
				String key = it.next();
				xStream.alias(key, aliasMap.get(key));
			}
		}
		xStream.registerConverter(new BlobConverter());
		xStream.registerConverter(new NullToXmlConverter());
		xStream.registerConverter(new IntegerConverter());
		xStream.registerConverter(new DateConverter());
		return xml==null||xml.trim().equals("")?null:xStream.fromXML(checkXmlChar(xml));
	}
	
	/**
	 * 过滤XML特殊字符
	 * @author LiuYang
	 * @param txt
	 * @return
	 */
	public static String filterSpecialCharOfXml(String txt){  
	    String res = "";  
	        for(int i = 0; i < txt.length(); ++i){  
	            char ch = txt.charAt(i);  
	            if( Character.isDefined(ch) &&  
	                ch!= '&' && ch != '<' && ch != '>' &&   
	                !Character.isHighSurrogate(ch) &&  
	                !Character.isISOControl(ch) &&  
	                !Character.isLowSurrogate(ch)  
	               ){  
	                res = res + ch;  
	            }  
	        }  
	        return res;  
	}  
	
	/** 
     * @see  ://www.w3.org/TR/2004/REC-xml-20040204/#charsets
     *      All supported characters 
     * @param data  
     *          content in each field  
     * @return  
     *          regular content is filtered from illegal XML char 
     */  
    public static String checkXmlChar(String data) {  
        StringBuffer appender = new StringBuffer("");  
          
        if (!data.trim().equals("")) {  
            appender = new StringBuffer(data.length());  
              
            for (int i = 0; i < data.length(); i++) {  
                char ch = data.charAt(i);  
                if ((ch == 0x9) || (ch == 0xA) || (ch == 0xD)  
                        || ((ch >= 0x20) && (ch <= 0xD7FF))  
                        || ((ch >= 0xE000) && (ch <= 0xFFFD))  
                        || ((ch >= 0x10000) && (ch <= 0x10FFFF)))  
                    appender.append(ch);  
            }  
        }  
          
        String result = appender.toString();  
          
        return result.replaceAll("]]>", "");  
    }


    /**
     * XML转JAVA对象
     * @param
     * @return
     */
    @SuppressWarnings("unchecked")
    public static Object xmlToObject(InputStream in,Map<String,Class> aliasMap){
        XStream xStream=new XStream(new DomDriver());
        if (aliasMap != null && aliasMap.size() > 0) {
            Iterator<String> it = aliasMap.keySet().iterator();
            while (it.hasNext()) {
                String key = it.next();
                xStream.alias(key, aliasMap.get(key));
            }
        }

        xStream.setMode(XStream.NO_REFERENCES);
        xStream.registerConverter(new BlobConverter());
        xStream.registerConverter(new NullFromXmlConverter());
        xStream.registerConverter(new IntegerConverter());
        xStream.registerConverter(new DateConverter());

        return in==null?null:xStream.fromXML(in);
    }
	
	/**
	 * 请求参数的XML转换为Map对象：如<map><status>1</status><page></page></map>
	 * @param ret
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static Map<String,String> paramXmlToMap(String ret)throws Exception{
		Map<String,String> rmap = new HashMap<String,String>();
		if(ret!=null&&!ret.trim().equals("")){
			SAXBuilder builder = new SAXBuilder();
			StringReader reader = new StringReader(ret.trim());
			Document doc = builder.build(new InputSource(reader));
			Element root = doc.getRootElement();
			List<Element> list = (List<Element>)root.getChildren();
			for(Element e:list){
				rmap.put(e.getName().trim().toUpperCase(), e.getText()!=null&&!e.getText().trim().equals("")?e.getText().trim():null);
			}
			return rmap;
		}
		return null;
	}
	
	public static void main(String[] args) {
		
	}
	
	public static boolean writeData(String wjdata, String filePath,String suffix) throws Exception {
		/**
		 * 处理特殊字符
		 */
		wjdata = wjdata.replace("&#xd;", "").replace("&#x1a;", "").replace("&#x1c;", "").replace("&#x7;", "");
		boolean flag = false;
		File file = new File(filePath);
		if (!file.exists()) {
			file.mkdirs();
		}
//		String wjPath = filePath+"/"+ZipUtils.generateFileName(suffix);
		String wjPath = filePath+"."+suffix;
		OutputStreamWriter out = null;
		try {
			out = new OutputStreamWriter(new FileOutputStream(wjPath,false),"UTF-8");
			out.write(wjdata);
			out.flush();
			flag = true;
		} catch (Exception e) {
			e.printStackTrace();
			throw new Exception("写文件错误！");
		} finally {
			if (out != null) {
				out.close();
				out =null;
			}
		}
		return flag;
	}
	//山东政法委
	public static boolean SdwriteData(String wjdata, String filePath,String suffix) throws Exception {
		/**
		 * 处理特殊字符
		 */
		wjdata = wjdata.replace("&#xd;", "").replace("&#x1a;", "").replace("&#x1c;", "").replace("&#x7;", "");
		boolean flag = false;
		File file = new File(filePath);
		if (!file.exists()) {
			file.mkdirs();
		}
//		String wjPath = filePath+"/"+ZipUtils.generateFileName(suffix);
		String wjPath = filePath+suffix;
		OutputStreamWriter out = null;
		try {
			out = new OutputStreamWriter(new FileOutputStream(wjPath,false),"UTF-8");
			out.write(wjdata);
			out.flush();
			flag = true;
		} catch (Exception e) {
			e.printStackTrace();
			throw new Exception("写文件错误！");
		} finally {
			if (out != null) {
				out.close();
				out =null;
			}
		}
		return flag;
	}
	
	public static void copyFile(File srcfile, String destPath){
		try {
			destPath = destPath.replace("\\", "/");
			File f = new File(destPath.substring(0,destPath.lastIndexOf("/")));
			if(!f.exists()){
				f.mkdirs();
			}
			int len = 0;
			if (srcfile.exists()) {
				InputStream in = new FileInputStream(srcfile);
				FileOutputStream out = new FileOutputStream(destPath);
				byte[] buffer = new byte[1024];
				while ((len = in.read(buffer)) != -1) {
					out.write(buffer, 0, len);
				}
				in.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
